package com.jianqiao.delivery.delivery.service.impl;

import com.jianqiao.delivery.delivery.service.OcrService;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @description:  图片文字识别实现类
 * @author: lsx
 * @create: 2024-11-25 14:44
 **/
@Service
public class OcrServiceImpl implements OcrService {

    private final Tesseract tesseract;

    public OcrServiceImpl(Tesseract tesseract) {
        this.tesseract = tesseract;
    }

    /**
     *
     * @param imageFile 要识别的图片
     * @return
     */
    @Override
    public String recognizeText(MultipartFile imageFile) throws IOException, TesseractException {
        // 转换
        InputStream sbs = new ByteArrayInputStream(imageFile.getBytes());
        BufferedImage bufferedImage = ImageIO.read(sbs);

        // 对图片进行文字识别
        String address = tesseract.doOCR(bufferedImage);

//        // 去除OCR识别结果中的空格    --对英文和印尼文不可用，因为单词间有空格
//        address = address.replaceAll("\\s+", "");
//        // 不知道为什么日语识别包会把数字识别成带圈的数字    --如果是tess4j的5.x.x版本,可注释
        address = convertCircledNumbers(address);

        // 打印OCR识别结果
        System.out.println("OCR识别结果: " + address);
        return address;
    }

    // 地址拆分
    @Override
    public Map Address(String address){
        Map<String, Object> res = new HashMap<>();
        res.put("address" , address);

        // 正则表达式模式，使用英文标签名称
        Pattern pattern = Pattern.compile(
                "^(?<prefecture>[^都道府県]+[都道府県])" +  // 都道府県
                        "(?<district>[^区市町村]+[区市町村])" +     // 市区町村
                        "(?<block>.+?丁目)" +                       // 街区（例如：3丁目、2丁目、1条2丁目等）
                        "(?<detailAddress>.+?)" +                          // 详细地址，直到遇到电话号码
                        "(?<name>(?:\\p{Script=Han}|\\p{Script=Hiragana}|\\p{Script=Katakana}){2,})?" +  // 日本名字
                        "(?<phone>\\d{2,4}-\\d{1,4}-\\d{4}|\\d{10,11})$"  // 电话号码，支持带连字符和不带连字符的格式                     // 电话号码，10到11位数字
        );

        Matcher matcher = pattern.matcher(address);
        if (matcher.find()) {
            res.put("province",matcher.group("prefecture"));
            res.put("district",matcher.group("district"));
            res.put("block",matcher.group("block"));
            res.put("detailAddress",matcher.group("detailAddress"));
            res.put("name",matcher.group("name"));
            res.put("phone",matcher.group("phone"));
            return res;
        } else {
            res.put("error","无法匹配");
            return res;
        }
    }

    // 将带圈的数字转换为普通数字
    private String convertCircledNumbers(String text) {
        Map<Character, Integer> circledNumberMap = new HashMap<>();
        circledNumberMap.put('①', 1);
        circledNumberMap.put('②', 2);
        circledNumberMap.put('③', 3);
        circledNumberMap.put('④', 4);
        circledNumberMap.put('⑤', 5);
        circledNumberMap.put('⑥', 6);
        circledNumberMap.put('⑦', 7);
        circledNumberMap.put('⑧', 8);
        circledNumberMap.put('⑨', 9);
        circledNumberMap.put('⑩', 10);
        circledNumberMap.put('⑪', 11);
        circledNumberMap.put('⑫', 12);
        circledNumberMap.put('⑬', 13);
        circledNumberMap.put('⑭', 14);
        circledNumberMap.put('⑮', 15);
        circledNumberMap.put('⑯', 16);
        circledNumberMap.put('⑰', 17);
        circledNumberMap.put('⑱', 18);
        circledNumberMap.put('⑲', 19);
        circledNumberMap.put('⑳', 20);

        StringBuilder result = new StringBuilder();
        int i = 0;
        while (i < text.length()) {
            char c = text.charAt(i);
            if (circledNumberMap.containsKey(c)) {
                int number = circledNumberMap.get(c);
                result.append(number);
                i++;
            } else {
                result.append(c);
                i++;
            }
        }
        return result.toString();
    }
}

